package com.audaque.springboot.foshanupload.web.util;

import com.audaque.springboot.foshanupload.core.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.management.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Function;

public class IpUtils {
    private static final Logger log = LoggerFactory.getLogger(IpUtils.class);
    private static final String IP_REGEX = "((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))";
    public static final String IP_UNKNOWN = "unknown";
    public static final String IPV4_LOCAL = "localhost";
    public static final String IPV6_LOCAL = "0:0:0:0:0:0:0:1";
    public static final int IP_LEN = 15;
    private static String localAddress;

    public IpUtils() {
    }

    public static boolean validateIp(String ip) {
        return StringUtils.isNotBlank(ip) && ip.matches("((25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))");
    }

    public static String getInetAddress() {
        if (localAddress != null) {
            return localAddress;
        } else {
            try {
                Enumeration allNetworkInterfaces = NetworkInterface.getNetworkInterfaces();

                while (true) {
                    NetworkInterface networkInterface;
                    do {
                        do {
                            do {
                                do {
                                    if (!allNetworkInterfaces.hasMoreElements()) {
                                        return null;
                                    }

                                    networkInterface = (NetworkInterface) allNetworkInterfaces.nextElement();
                                } while (networkInterface.isLoopback());
                            } while (networkInterface.isVirtual());
                        } while (!networkInterface.isUp());
                    } while (networkInterface.getDisplayName().contains("VM"));

                    Enumeration inetAddressEnumeration = networkInterface.getInetAddresses();

                    while (inetAddressEnumeration.hasMoreElements()) {
                        InetAddress inetAddress = (InetAddress) inetAddressEnumeration.nextElement();
                        if (inetAddress != null && inetAddress instanceof Inet4Address) {
                            localAddress = inetAddress.getHostAddress();
                            return localAddress;
                        }
                    }
                }
            } catch (SocketException var4) {
                var4.printStackTrace();
                return null;
            }
        }
    }

    public static final String getHttpIp(HttpServletRequest request) {
        return getHttpIp((key) -> {
            return key == null ? request.getRemoteAddr() : request.getHeader(key);
        });
    }




    private static String getHttpIp(Function<String, String> function) {
        String ip = (String) function.apply("X-Real-IP");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply("X-Forwarded-For");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply("Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply("HTTP_CLIENT_IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply("HTTP_X_FORWARDED_FOR");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = (String) function.apply((String) null);
        }

        if (ip != null && ip.length() > 15) {
            String[] ips = ip.split(",");
            String[] var3 = ips;
            int var4 = ips.length;

            for (int var5 = 0; var5 < var4; ++var5) {
                String s = var3[var5];
                if (!"unknown".equalsIgnoreCase(s.trim())) {
                    return s;
                }
            }
        }

        return ip;
    }

    public static int findAvailablePort(int defaultPort) {
        int portTmp;
        for (portTmp = defaultPort; portTmp < 65535; ++portTmp) {
            if (!isPortUsed(portTmp)) {
                return portTmp;
            }
        }

        for (portTmp = defaultPort--; portTmp > 0; --portTmp) {
            if (!isPortUsed(portTmp)) {
                return portTmp;
            }
        }

        throw new RuntimeException("no available port.");
    }

    public static boolean isPortUsed(int port) {
        boolean used = false;
        ServerSocket serverSocket = null;

        try {
            serverSocket = new ServerSocket(port);
            used = false;
        } catch (IOException var12) {
            log.debug(">>>>>>>>>>> xxl-rpc, port[{}] is in use.", port);
            used = true;
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException var11) {
                    log.debug("");
                }
            }

        }

        return used;
    }

    public static int getTomcatPort() {
        int port = 0;
        MBeanServer mBeanServer = null;
        ArrayList<MBeanServer> mBeanServers = MBeanServerFactory.findMBeanServer((String) null);
        if (mBeanServers.size() > 0) {
            mBeanServer = (MBeanServer) mBeanServers.get(0);
        }

        if (mBeanServer == null) {
            throw new IllegalStateException("没有发现JVM中关联的MBeanServer.");
        } else {
            Set objectNames = null;

            try {
                objectNames = mBeanServer.queryNames(new ObjectName("Catalina:type=Connector,*"), (QueryExp) null);
            } catch (MalformedObjectNameException var8) {
                var8.printStackTrace();
            } catch (NullPointerException var9) {
                var9.printStackTrace();
            }

            if (objectNames == null || objectNames.size() <= 0) {
                try {
                    objectNames = mBeanServer.queryNames(new ObjectName("*:type=Connector,*"), Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
                } catch (MalformedObjectNameException var7) {
                    var7.printStackTrace();
                }
            }

            if (objectNames != null && objectNames.size() > 0) {
                try {
                    Iterator var4 = objectNames.iterator();

                    while (var4.hasNext()) {
                        ObjectName objectName = (ObjectName) var4.next();
                        String protocol = (String) mBeanServer.getAttribute(objectName, "protocol");
                        if (protocol.equals("HTTP/1.1")) {
                            port = (Integer) mBeanServer.getAttribute(objectName, "port");
                        }
                    }
                } catch (AttributeNotFoundException var10) {
                    var10.printStackTrace();
                } catch (InstanceNotFoundException var11) {
                    var11.printStackTrace();
                } catch (MBeanException var12) {
                    var12.printStackTrace();
                } catch (ReflectionException var13) {
                    var13.printStackTrace();
                }

                return port;
            } else {
                throw new IllegalStateException("没有发现JVM中关联的MBeanServer : " + mBeanServer.getDefaultDomain() + " 中的对象名称.");
            }
        }
    }

    public static void main(String[] args) {
        System.err.println(getInetAddress());
    }
}
